package com.hbt.android.kotlin.http

import android.content.Context
import android.os.Environment
import android.util.Log
import android.widget.Toast
import kotlinx.coroutines.flow.callbackFlow
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import java.io.File
import java.io.IOException
import java.util.concurrent.TimeUnit


fun main() {
    OkHttp.syncGet(OkHttp.BASE_GET_URL)
//    OkHttp.asyncGet(OkHttp.BASE_GET_URL)
//    OkHttp.syncPost(OkHttp.BASE_GET_URL)
//    OkHttp.asyncPost(OkHttp.BASE_GET_URL)
}

object OkHttp {
//    fun init() {
//        OkHttp.init()
//    }

    public const val BASE_GET_URL = "https://movie.querydata.org/api?id=1302425"
    private val client: OkHttpClient
    init {
        val httpLoggingInterceptor = HttpLoggingInterceptor()
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)

        client = OkHttpClient.Builder() // builder 构造者设计模式
            .connectTimeout(10, TimeUnit.SECONDS)   // 连接超时时间
            .readTimeout(10, TimeUnit.SECONDS)  // 读取超时
            .writeTimeout(10, TimeUnit.SECONDS) // 请求超时，
//            .addInterceptor(HttpLoggingInterceptor())// 内置的日志拦截器
//            .addInterceptor(LoggingInterceptor()) // 自定义的拦截器
            .addInterceptor(httpLoggingInterceptor) // 自定义的拦截器
            .build()
    }




    /**
     * 同步get请求
     */
    fun syncGet(url: String) {
        Thread(Runnable {
            val request: Request = Request.Builder()
                .url(url)
                .build()

            val call: Call = client.newCall(request)
            // 发起同步请求
            val response = call.execute()
            val body = response.body?.toString()

            Log.e("okhttp", "syncGet response :${body}")
        }).start()
    }

    /**
     * 异步get请求
     */
    fun asyncGet(url: String) {
        val request: Request = Request.Builder()
            .url(url)
            .build()

        val call: Call = client.newCall(request)
        // 发起异步请求
        val response = call.enqueue(object :Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.e("okhttp", "asyncGet onFailure :${e.localizedMessage}")
            }

            override fun onResponse(call: Call, response: Response) {
                val body = response.body?.toString()
                Log.e("okhttp", "asyncGet onResponse :${body}")
            }

        })
        val body = response.toString()

        Log.e("okhttp", "get response ${body}")

    }

    /**
     * 同步post请求
     */
    fun syncPost(url: String) {
        Thread(Runnable {
            val requestBody: FormBody = FormBody.Builder()
                .add("key", "value")
                .add("key", "value")
                .build()

            val request: Request = Request.Builder()
                .url(url)
                .post(requestBody)
                .build()
            val call: Call = client.newCall(request)

            val response = call.execute();
            val responseBody = response.body?.toString()
            Log.e("okhttp", "syncPost onResponse :${requestBody}")
        })
    }

    /**
     * 表单
     * 异步post请求
     */
    fun asyncPost(url: String) {
        val requestBody: FormBody = FormBody.Builder()
            .add("key", "value")
            .add("key", "value")
            .build()

        val request: Request = Request.Builder()
            .url(url)
            .post(requestBody)
            .build()
        val call: Call = client.newCall(request)

        val response = call.enqueue(object :Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.e("okhttp", "asyncPost onFailure :${e.localizedMessage}")
            }

            override fun onResponse(call: Call, response: Response) {
                val responseBody = response.body?.toString()
                Log.e("okhttp", "asyncPost onResponse :${responseBody}")
            }
        });
    }


    /**
     * 异步文件表单, android6.0以后读取外部存储卡的文件，都是需要动态申请权限
     */
    fun asyncPostMultipart(context: Context, url: String) {
        val file = File(Environment.getExternalStorageDirectory(), "1.png")
        if (!file.exists()) {
            Toast.makeText(context, "文件不存在", Toast.LENGTH_SHORT).show()
                return
        }


        val multipartBody: RequestBody = MultipartBody.Builder()
            .setType(MultipartBody.FORM)//一定要设置这句
            .addFormDataPart("username", "admin") //
            .addFormDataPart("password", "admin") //
            .addFormDataPart( "file", "1.png",RequestBody.create(
                "application/octet-stream".toMediaType(),
                file
            ))
            .build()
        val request: Request = Request.Builder()
            .url(url)
            .post(multipartBody)
            .build()
        val call: Call = client.newCall(request)

        val response = call.enqueue(object :Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.e("okhttp", "asyncPostMultipart onFailure :${e.localizedMessage}")
            }

            override fun onResponse(call: Call, response: Response) {
                val responseBody = response.body?.toString()
                Log.e("okhttp", "asyncPostMultipart onResponse :${responseBody}")
            }
        });

    }

    /**
     * 异步提交字符串
     */
    fun asyncPostString(context: Context, url: String) {

        // 字符串
//        val mediaType = "text/plain;charset=utf-8".toMediaType()
        // json
        val mediaType = "application/json;charset=utf-8".toMediaType()
        val jsonObject = JSONObject()
        jsonObject.put("key", "value")
        jsonObject.put("key", "value")
        val requestBody = RequestBody.create(mediaType, jsonObject.toString())
        val request: Request = Request.Builder()
            .url(url)
            .post(requestBody)
            .build()
        val call: Call = client.newCall(request)

        val response = call.enqueue(object :Callback{
            override fun onFailure(call: Call, e: IOException) {
                Log.e("okhttp", "asyncPostString onFailure :${e.localizedMessage}")
            }

            override fun onResponse(call: Call, response: Response) {
                val responseBody = response.body?.toString()
                Log.e("okhttp", "asyncPostString onResponse :${responseBody}")
            }
        });

    }
}

